// 例如， 罗马数字 2 写做 II ，即为两个并列的 1。12 写做 XII ，即为 X + II 。 27 写做  XXVII, 即为 XX + V + II 。

// 通常情况下，罗马数字中小的数字在大的数字的右边。但也存在特例，例如 4 不写做 IIII，而是 IV。数字 1 在数字 5 的左边，所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地，数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况：

// I 可以放在 V (5) 和 X (10) 的左边，来表示 4 和 9。
// X 可以放在 L (50) 和 C (100) 的左边，来表示 40 和 90。 
// C 可以放在 D (500) 和 M (1000) 的左边，来表示 400 和 900。
// 给定一个罗马数字，将其转换成整数。输入确保在 1 到 3999 的范围内。

function roman2num (roman: string): number {
    if (!roman) {
        return 0;
    }
    const map = {
        I: 1,
        V: 5,
        X: 10,
        L: 50,
        C: 100,
        D: 500,
        M: 1000,
    };
    // letter: 字母
    // III    letter: I  map[letter]: 1
    // IV
    let sum = map[roman.substr(-1)];
    // for (const letter of roman) {
    //     const num = map[letter];
    //     sum += num;
    // }
    // MCMXCIV 
    for (let i = roman.length - 2; i >= 0; i--) {
        const rightLetter = roman[i + 1];
        const currentLetter = roman[i];
        if (map[currentLetter] < map[rightLetter]) {
            sum -= map[currentLetter];
        } else {
            sum += map[currentLetter];
        }
    }
    return sum;
}

function roman2num1 (roman: string): number {
    if (!roman) {
        return 0;
    }
    const map = new Map([
        ['I', 1],
        ['V', 5],
        ['X', 10],
        ['L', 50],
        ['C', 100],
        ['D', 500],
        ['M', 1000],
    ]);
    // const map = {
    //     I: 1,
    //     V: 5,
    //     X: 10,
    //     L: 50,
    //     C: 100,
    //     D: 500,
    //     M: 1000,
    // };
    // letter: 字母
    // III    letter: I  map[letter]: 1
    // IV
    let sum = map.get(roman.substr(-1));
    // for (const letter of roman) {
    //     const num = map[letter];
    //     sum += num;
    // }
    // MCMXCIV 
    for (let i = roman.length - 2; i >= 0; i--) {
        const rightLetter = roman[i + 1];
        const currentLetter = roman[i];
        const currentNum = map.get(currentLetter);
        const rightNum = map.get(rightLetter);
        if (currentNum < rightNum) {
            sum -= currentNum;
        } else {
            sum += currentNum;
        }
    }
    return sum;
}

function getNum (letter: string): number {
    switch (letter) {
        case 'I': return 1;
        case 'V': return 5;
        case 'X': return 10;
        case 'L': return 50;
        case 'C': return 100;
        case 'D': return 500;
        case 'M': return 1000;
        default: return 0;
    }
}

function roman2num2 (roman: string): number {
    if (!roman) {
        return 0;
    }
    // letter: 字母
    // III    letter: I  map[letter]: 1
    // IV
    let sum = getNum(roman.substr(-1));
    // for (const letter of roman) {
    //     const num = map[letter];
    //     sum += num;
    // }
    // MCMXCIV 
    for (let i = roman.length - 2; i >= 0; i--) {
        const rightLetter = roman[i + 1];
        const currentLetter = roman[i];
        const currentNum = getNum(currentLetter);
        const rightNum = getNum(rightLetter);
        if (currentNum < rightNum) {
            sum -= currentNum;
        } else {
            sum += currentNum;
        }
    }
    return sum;
}

console.log( roman2num('MCMXCIV') ); // 1994

function p1 (name, cb, count) {
    console.time(name);
    for (let i = 0; i < count; i++) {
        cb();
    }
    console.timeEnd(name);
}

p1('对象', () => {
    roman2num('MCMXCIV')
}, 100000);

p1('映射', () => {
    roman2num1('MCMXCIV')
}, 100000);

p1('Switch', () => {
    roman2num2('MCMXCIV')
}, 100000);